"""
HTTP请求工具类
支持GET请求和POST请求(表单提交和raw提交)
"""
import json
import requests
import os
from Sinszm.common_util import CommonUtil

class HttpUtil:

    @staticmethod
    def get(url, params=None, headers=None, timeout=30):
        """
        发送GET请求
        :param url: 请求URL
        :param params: URL参数，字典形式
        :param headers: 请求头，字典形式
        :param timeout: 超时时间，默认30秒
        :return: 响应结果，JSON格式
        """
        # 获取日志记录器
        http_logger = CommonUtil.logger("HttpUtil")
        try:
            # 默认请求头
            default_headers = {
                'Accept': 'application/json',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36'
            }
            # 合并请求头
            request_headers = default_headers.copy()
            if headers:
                request_headers.update(headers)
            http_logger.debug(f"发送GET请求: {url}, 参数: {params}")
            response = requests.get(url, params=params, headers=request_headers, timeout=timeout)
            response.raise_for_status()  # 如果状态码不是200，抛出异常
            # 尝试解析JSON响应
            try:
                result = response.json()
                http_logger.debug(f"GET请求成功，URL: {url}, 响应: {result}")
                return result
            except json.JSONDecodeError:
                # 如果响应不是有效的JSON，返回空字典
                http_logger.warning(f"GET请求响应不是有效的JSON: {url}")
                return {}
        except requests.exceptions.RequestException as e:
            http_logger.error(f"GET请求失败: {url}, 错误: {str(e)}")
            # 返回错误信息，保持JSON格式
            return {
                "status": "error",
                "code": getattr(e, 'response', None) and getattr(e.response, 'status_code', None) or 500,
                "message": str(e)
            }
    

    @staticmethod
    def post_form(url, data=None, headers=None, timeout=30):
        """
        发送POST表单请求
        :param url: 请求URL
        :param data: 表单数据，字典形式
        :param headers: 请求头，字典形式
        :param timeout: 超时时间，默认30秒
        :return: 响应结果，JSON格式
        """
        # 获取日志记录器
        http_logger = CommonUtil.logger("HttpUtil")
        try:
            # 默认请求头
            default_headers = {
                'Accept': 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36'
            }
            # 合并请求头
            request_headers = default_headers.copy()
            if headers:
                request_headers.update(headers)
            http_logger.debug(f"发送POST表单请求: {url}, 数据: {data}")
            response = requests.post(url, data=data, headers=request_headers, timeout=timeout)
            response.raise_for_status()  # 如果状态码不是200，抛出异常
            # 尝试解析JSON响应
            try:
                result = response.json()
                http_logger.debug(f"POST表单请求成功，URL: {url}, 响应: {result}")
                return result
            except json.JSONDecodeError:
                # 如果响应不是有效的JSON，返回空字典
                http_logger.warning(f"POST表单请求响应不是有效的JSON: {url}")
                return {}
        except requests.exceptions.RequestException as e:
            http_logger.error(f"POST表单请求失败: {url}, 错误: {str(e)}")
            # 返回错误信息，保持JSON格式
            return {
                "status": "error",
                "code": getattr(e, 'response', None) and getattr(e.response, 'status_code', None) or 500,
                "message": str(e)
            }
    

    @staticmethod
    def post_raw(url, data=None, headers=None, timeout=30):
        """
        发送POST raw请求（通常是JSON数据）
        :param url: 请求URL
        :param data: 请求体数据，可以是字典或字符串
        :param headers: 请求头，字典形式
        :param timeout: 超时时间，默认30秒
        :return: 响应结果，JSON格式
        """
        # 获取日志记录器
        http_logger = CommonUtil.logger("HttpUtil")
        try:
            # 默认请求头
            default_headers = {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36'
            }
            # 合并请求头
            request_headers = default_headers.copy()
            if headers:
                request_headers.update(headers)
            # 如果data是字典，转换为JSON字符串
            request_data = data
            if isinstance(data, dict):
                request_data = json.dumps(data)
            http_logger.debug(f"发送POST raw请求: {url}, 数据: {request_data}")
            response = requests.post(url, data=request_data, headers=request_headers, timeout=timeout)
            response.raise_for_status()  # 如果状态码不是200，抛出异常
            # 尝试解析JSON响应
            try:
                result = response.json()
                http_logger.debug(f"POST raw请求成功，URL: {url}, 响应: {result}")
                return result
            except json.JSONDecodeError:
                # 如果响应不是有效的JSON，返回空字典
                http_logger.warning(f"POST raw请求响应不是有效的JSON: {url}")
                return {}
        except requests.exceptions.RequestException as e:
            http_logger.error(f"POST raw请求失败: {url}, 错误: {str(e)}")
            # 返回错误信息，保持JSON格式
            return {
                "status": "error",
                "code": getattr(e, 'response', None) and getattr(e.response, 'status_code', None) or 500,
                "message": str(e)
            }

    @staticmethod
    def download_file(url, save_path, headers=None, timeout=60):
        """
        下载文件
        :param url: 文件URL
        :param save_path: 保存路径
        :param headers: 请求头，字典形式
        :param timeout: 超时时间，默认60秒
        :return: 布尔值，表示下载是否成功
        """
        # 获取日志记录器
        http_logger = CommonUtil.logger("HttpUtil")
        try:
            # 默认请求头
            default_headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36'
            }
            # 合并请求头
            request_headers = default_headers.copy()
            if headers:
                request_headers.update(headers)
            
            http_logger.debug(f"开始下载文件: {url}")
            # 使用stream参数进行流式下载
            with requests.get(url, headers=request_headers, timeout=timeout, stream=True) as response:
                response.raise_for_status()  # 如果状态码不是200，抛出异常
                
                # 获取文件大小
                total_size = int(response.headers.get('content-length', 0))
                downloaded_size = 0
                
                # 确保目录存在
                os.makedirs(os.path.dirname(save_path), exist_ok=True)
                
                # 分块写入文件
                with open(save_path, 'wb') as file:
                    for chunk in response.iter_content(chunk_size=8192):
                        if chunk:  # 过滤掉保持连接的空块
                            file.write(chunk)
                            downloaded_size += len(chunk)
                            
                http_logger.info(f"文件下载成功: {save_path}, 文件大小: {total_size/1024:.2f}KB")
                return True
        except requests.exceptions.RequestException as e:
            http_logger.error(f"文件下载失败: {url}, 错误: {str(e)}")
            return False
        except IOError as e:
            http_logger.error(f"文件保存失败: {save_path}, 错误: {str(e)}")
            return False
